home *** CD-ROM | disk | FTP | other *** search
Modula Implementation | 1993-12-06 | 5.0 KB | 160 lines |
- IMPLEMENTATION MODULE GEMX;
-
- (* Rekompiliertes LPR-Originalmodul mit Ergaenzungen fuer Modulterminierung
- * und ACCs.
- *
- * Dieses Modul und die Modulterminierung in LPRTERMINATION werden nur bei
- * gelinkten Programmen ausgefuehrt, nicht jedoch bei Programmen, die unter
- * Kontrolle des Laders laufen!
- *
- * Die Programmierung von ACCs ist nur moeglich, wenn nach dem Linken
- * der RECORD vom Typ ExtInfo direkt hinter dem Programmheader
- * und die BSS-Laenge entsprechend gepatched werden, da der Stackpointer
- * gesetzt werden muss, bevor ein Initialisierungsteil eines Moduls
- * ausgefuehrt wird (bei einem ACC ist SP NICHT initialisiert!), und
- * beim Laden von ACCs automatisch aller Speicher freigegeben wird, sodass
- * Heap und Stack in der BSS beruecksichtigt werden muessen!
- * Es kann entweder der Linker direkt mit FIXLINK.TOS gepatched werden,
- * sodass keine weiteren Aenderungen an den Programmdateien notwendig
- * sind, oder mit FIXPRG.TOS die einzelne Programmdatei. Letzteres kann
- * auch erforderlich sein, wenn andere Werte fuer Stack- und Heapgroesse
- * benoetigt werden.
- *
- * Dateioffset: Code: Befehl:
- * $A DC.L <BssLen> := <heapSize> + <stackSize>
- *
- * $1C 6000 000A bra tstacc
- * $20 xxxx xxxx DC.L <heapSize>
- * $24 xxxx xxxx DC.L <stackSize>
- * $28 tstacc: B0FC 0000 cmpa.w #0,A0 ; ACC ?
- * $2C 670A beq.s init ; B: nein, wie gehabt
- * $2E 4FE8 0100 lea 256(A0),SP ; vorl. Stack in Kommandozeile
- * $32 6004 bra.s init
- * $34 xxxx xxxx DC.L <modBase>
- * $38 init: ....
- *
- * Falls die fuer den HALT-Befehl definierte Routine das Programm nicht
- * beendet (die Standardroutine gibt bei gelinkten Programmen nur eine
- * Meldung), wird das Programm nach Ausfuehren der Terminierungsroutinen
- * beendet.
- *
- * 27-Nov-93, Holger Kleinschmidt
- *)
-
- FROM System IMPORT
- (* TYPE *) HaltProc,
- (* VAR *) HALTX0;
-
- FROM SYSTEM IMPORT
- (* TYPE *) ADDRESS,
- (* PROC *) VAL, REG, SETREG, INLINE;
-
- FROM LPRTERMINATION IMPORT
- (* VAR *) BasePageP,
- (* PROC *) FINALIZE, IsAPP;
-
- (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
-
- CONST
- MINFREE = 16384D; (* mindestens 16kB an TOS zurueckgeben *)
-
- ENSMEM = -39;
-
- PTERM = 76D;
- MSHRINK = 74D;
-
- d0 = 0;
- sp = 15;
-
-
- PROCEDURE Pterm (p1,f:INTEGER); CODE(4E41H);
- PROCEDURE Mshrink (p3:LONGINT;p2:ADDRESS;p1,f:CARDINAL); CODE(4E41H);
-
- VAR
- start : PROC;
- (* Der Inhalt von 'start' wird vom Linker eingesetzt. Deswegen
- * darf keine weitere Variable im Definitionsmodul deklariert
- * werden, und 'start' muss hier an erster Stelle stehen, damit sich
- * die Adresse der Variable nicht aendert!!
- *)
- pEnd : LONGINT;
- pLen : LONGINT;
- Info : ExtInfoPtr;
- ret : INTEGER;
- acc : BOOLEAN;
- halt : HaltProc;
-
- (*===========================================================================*)
-
- PROCEDURE PrgHALT;
- (* Hier auf keinen Fall HALTX verwenden, sonst Endlosrekursion, da diese
- * Prozedur (die auch bei einem HALT verwendet wird), die Prozedur, die
- * in HALTX0 gespeichert ist, ausfuehrt.
- *)
- BEGIN
- halt; (* Alte HALT-Routine ausfuehren *)
- (* Falls die HALT-Routine zurueckkehrt, Programm beenden *)
- FINALIZE(ret);
- Pterm(ret, PTERM);
- END PrgHALT;
-
- (*===========================================================================*)
-
- BEGIN (* GEMX *)
- acc := NOT IsAPP();
- IF acc THEN
- (* Die Basepage wird in 'LPRTERMINATION' ermittelt und hier gesetzt *)
- BasePagePtr := VAL(ADDRESS,BasePageP);
- BasePagePtr^.BssLen := 0D;
- (* Noetig fuer 'Heap' (oder die Initialisierung von 'Heap' muss geaendert
- * werden).
- * In der Hoffnung, dass 'BssLen' weder vom Betriebssystem noch
- * vom Programm mehr benoetigt wird...
- * 'BssLen' == 'heapSize' + stackSize'
- *)
- ELSE
- (* Die Basepage wird hier ermittelt und in 'LPRTERMINATION' gesetzt *)
- INLINE(202FH, 12); (* move.l 12(SP),D0 *)
- BasePagePtr := VAL(ADDRESS,REG(d0));
- BasePageP := VAL(ADDRESS,BasePagePtr);
- END;
-
- WITH BasePagePtr^ DO
- Info := VAL(ExtInfoPtr,CodeBase);
- pEnd := CodeBase + CodeLen + DataLen;
- END;
- WITH Info^ DO
- (* Anstatt 'BssLen' zu addieren *)
- INC(pEnd, heapSize + stackSize);
- END;
- IF ODD(pEnd) THEN
- INC(pEnd);
- END;
-
- IF acc THEN
- SETREG(sp, pEnd); (* endgueltigen Stack auf Ende der BSS setzen *)
- start; (* kehrt nicht zurueck! *)
- END;
-
- IF pEnd < BasePagePtr^.HighTPA - MINFREE THEN
- (* Programm nur ausfuehren, wenn genuegend Platz *)
- pLen := pEnd - BasePagePtr^.LowTPA;
- SETREG(sp, pEnd); (* Stack setzen *)
-
- Mshrink(pLen, BasePagePtr, 0, MSHRINK);
- INLINE(4FEFH, 12); (* lea 12(SP),SP *)
-
- BasePagePtr^.HighTPA := pEnd;
-
- halt := HALTX0; (* Alte HALT-Routine merken *)
- HALTX0 := PrgHALT; (* Neue HALT-Routine installieren *)
-
- start; (* Programm ausfuehren *)
-
- FINALIZE(ret); (* Terminierungsroutinen ausfuehren *)
- Pterm(ret, PTERM);
- ELSE
- Pterm(ENSMEM, PTERM);
- END;
- END GEMX.
-